#ifndef __WIZ_SP_BASE_HPP__SHANHAOBO_19800429__
#define __WIZ_SP_BASE_HPP__SHANHAOBO_19800429__

#include "./WizSPTrace.hpp"

namespace Wiz
{
    namespace SP
    {
        template
        <
            class               LocationT,
            class               DataT,
            class               BoxT,
            class               TraceResultT,
            class               WorldSizeT      = ::Wiz::Real::Type,
            ::Wiz::UInt::Type   IMaxWorldSize   = 512 * 1024,
            class               BaseT           = ::Wiz::Null::Type
        >
        struct Type : public BaseT
        {
            //////////////////////////////////////////////////////////////////////////
            typedef LocationT                                   tLocation;
            WIZ_DECLARE_IO_WITHNAME(LocationT, tLocation)

            WIZ_DECLARE_CLASS_TYPE(DataT, tData);
            typedef ::Wiz::Array::Type<tData>                   tDataArray;
            typedef tDataArray&                                 tDataArrayRef;
            typedef tDataArray&                                 tDataArrayOut;

            typedef BoxT                                        tBox;
            WIZ_DECLARE_IO_WITHNAME(BoxT, tBox)

            typedef TraceResultT                                tTraceResult;
            typedef ::Wiz::Array::Type<tTraceResult>            tTraceResultArray;
            typedef tTraceResultArray &                         tTraceResultArrayOut;

            typedef WorldSizeT                                  tWorldSize;
            WIZ_DECLARE_IO_WITHNAME(WorldSizeT, tWorldSize)

            typedef ::Wiz::SP::Trace::Info::Type tTraceInfo;

            //////////////////////////////////////////////////////////////////////////
            enum
            {
                eMaxWorldSize  = IMaxWorldSize,
                eHalfWorldSize = IMaxWorldSize >> 1,
            };

            //////////////////////////////////////////////////////////////////////////
        public:
            WIZ_INLINE tWorldSize MaxWorldSize() const
            {
                static const tElement s_MaxWorldSize(eMaxWorldSize);
                return s_MaxWorldSize;
            }

            WIZ_INLINE tWorldSize HalfWorldSize() const
            {
                static const tWorldSize s_HalfWorldSize(eHalfWorldSize);
                return s_HalfWorldSize;
            }

            WIZ_INLINE tWorldSize HalfWorldSizeSqr() const
            {
                static const tWorldSize s_HalfWorldSize(HalfWorldSize() * HalfWorldSize());
                return s_HalfWorldSize;
            }

            //////////////////////////////////////////////////////////////////////////
        public:
            Type() : BaseT()
            {

            }

            template<class T>
            Type(const T& InT) : BaseT(InT)
            {

            }

            template<class T, class U>
            Type(const T& InT, const U& InU) : BaseT(InT, InU)
            {

            }

            virtual ~Type()
            {

            };

            //////////////////////////////////////////////////////////////////////////
        public:
            virtual ::Wiz::Bool::Type LineTrace(
                tTraceResultArrayOut    OutTraceResult,
                tLocationIn             InStart,
                tLocationIn             InEnd,
                tTraceInfo&             InTraceInfo,
                tBoxIn                  InExtent
                )
            {
                if (InExtent.IsValid())
                {
                    return LineTrace_NonExtent(OutTraceResult, InStart, InEnd, InTraceInfo);
                }

                return LineTrace_Extent(OutTraceResult, InStart, InEnd, InTraceInfo, InExtent);
            }
        protected:
            virtual ::Wiz::Bool::Type LineTrace_NonExtent(
                tTraceResultArrayOut    OutTraceResult,
                tLocationIn             InStart,
                tLocationIn             InEnd,
                tTraceInfo&             InTraceInfo
                ) = 0;

            virtual ::Wiz::Bool::Type LineTrace_Extent(
                tTraceResultArrayOut    OutTraceResult,
                tLocationIn             InStart,
                tLocationIn             InEnd,
                tTraceInfo&             InTraceInfo,
                tBoxIn                  InExtent
                ) = 0;

            //////////////////////////////////////////////////////////////////////////
        public:
            virtual ::Wiz::Bool::Type PointTrace(
                tTraceResultArrayOut    OutTraceResult,
                tLocationIn             InLocation,
                tTraceInfo&             InTraceInfo,
                tBoxIn                  InExtent
                )
            {
                if (InExtent.IsValid())
                {
                    return PointTrace_NonExtent(OutTraceResult, InLocation, InTraceInfo);
                }

                return PointTrace_Extent(OutTraceResult, InLocation, InTraceInfo, InExtent);
            }
        protected:
            virtual ::Wiz::Bool::Type PointTrace_NonExtent(
                tTraceResultArrayOut    OutTraceResult,
                tLocationIn             InLocation,
                tTraceInfo&             InTraceInfo
                ) = 0;

            virtual ::Wiz::Bool::Type PointTrace_Extent(
                tTraceResultArrayOut    OutTraceResult,
                tLocationIn             InLocation,
                tTraceInfo&             InTraceInfo,
                tBoxIn                  InExtent
                ) = 0;

            //////////////////////////////////////////////////////////////////////////
        };
    } /// end of namespace SP
} /// end of namespace Wiz

#endif /*__WIZ_SP_BASE_HPP__SHANHAOBO_19800429__*/
